use std::path::Path;

use bc_base::{BlockId, block::BlockInDb};
use bc_db::DBError;

use crate::inner_storage::StorageBase;

#[derive(Debug)]
pub(crate) struct BlockStorage {
    block_db: StorageBase<BlockId, BlockInDb>,
}

impl BlockStorage {
    pub(crate) fn new(db_root_dir: &Path) -> Result<Self, DBError> {
        let path = crate::get_blocks_db_path(db_root_dir);
        tracing::info!(
            ">>>> The path of BlockStorage DB: {}",
            path.to_str().unwrap()
        );
        Ok(Self {
            block_db: StorageBase::new(&path)?,
        })
    }

    pub(crate) async fn put(&self, key: &BlockId, value: &BlockInDb) -> Result<(), DBError> {
        self.block_db.put(key, value).await
    }
    pub(crate) async fn get(&self, key: &BlockId) -> Result<Option<BlockInDb>, DBError> {
        self.block_db.get(key).await
    }
    pub(crate) async fn erase(&self, key: &BlockId) -> Result<(), DBError> {
        self.block_db.erase(key).await
    }

    pub(crate) async fn exists(&self, key: &BlockId) -> bool {
        self.block_db.exists(key).await
    }

    pub(crate) async fn flush_database(&self) -> Result<(), DBError> {
        self.block_db.flush_database().await
    }

    #[cfg(debug_assertions)]
    pub(crate) async fn get_item_number(&self) -> usize {
        self.block_db.get_item_number().await
    }
}
